<template>
  <div class="main-wrap">
    <div class="tool-warp">
      <el-tooltip
        effect="dark"
        content="扫码添加"
        placement="top"
      >
        <el-button type="primary" :icon="CameraFilled" size="small" circle @click="handleScan"/>
      </el-tooltip>
      <el-tooltip
        effect="dark"
        content="手动添加"
        placement="top"
      >
        <el-button type="primary" :icon="Plus" size="small" circle @click="handleAdd"/>
      </el-tooltip>
      <el-tooltip
        effect="dark"
        content="删除历史"
        placement="top"
      >
        <el-button type="primary" :icon="Delete" size="small" circle @click="handleOpenHis"/>
      </el-tooltip>
    </div>

    <el-scrollbar height="300px">
      <el-empty description="还没有数据，快去添加吧！" v-if="serverData.length <= 0"/>
      <div class="code-wrap" v-else>
        <div class="code-item" v-for="item in serverData" :key="item.id" @click="handleCopy(item)">
          <div class="code-title">
            <div class="title-text">{{ item.name }}</div>
            <div class="title-time">{{ item.time }}</div>
          </div>
          <div class="tool-wrap">
            <div class="left-tool">
              <h1>{{ item.code }}</h1>
            </div>
            <div class="right-tool">
              <el-button type="danger" link @click.stop="handleDelete(item.id)">删除</el-button>
              <el-button type="success" link @click.stop="handleCopy(item)">复制</el-button>
            </div>
          </div>
        </div>
      </div>
    </el-scrollbar>

    <el-dialog v-model="showFlag" fullscreen>
      <el-form v-model="form" style="margin-top: 30px;">
        <el-form-item label="名称" required>
          <el-input v-model="from.name" placeholder="自定义名称" />
        </el-form-item>
        <el-form-item label="密钥" required>
          <el-input v-model="from.secret" placeholder="请输入密钥" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="showFlag = false">取消</el-button>
          <el-button type="primary" @click="handleConfirm">添加</el-button>
        </div>
      </template>
    </el-dialog>

    <el-dialog v-model="hisFlag" fullscreen>
      <el-table :data="hisList" empty-text="暂无删除历史数据">
        <el-table-column property="name" label="name" />
        <el-table-column property="secret" label="secret" />
        <el-table-column label="操作" width="100">
          <template #default="scope">
            <el-button link type="danger" size="small" @click="handleHisDelete(scope.row.id)">删除</el-button>
            <el-button link type="primary" size="small" @click="handleHisBack(scope.row)">恢复</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>

<script setup>
import { CameraFilled, Plus, Delete } from '@element-plus/icons-vue'
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { BrowserMultiFormatReader } from '@zxing/library'
import { ElMessage } from 'element-plus'
import { TOTP } from "totp-generator"
import { v4 as uuidv4 } from 'uuid'

const serverData = ref([])
const timeMap = new Map()
const showFlag = ref(false)
const hisFlag = ref(false)
const from = ref({
  name: '',
  secret: ''
})
const hisList = ref([])

onMounted(() => {
  chrome.storage.local.get(["authKey"]).then((result) => {
    console.log("Value currently is ", result.authKey)
    if (!result.authKey) {
      return
    }
    const list = JSON.parse(result.authKey)
    console.log('data:', list)
    if (list) {
      for(let i = 0; i < list.length; i++) {
        try{
          const target = list[i]
          const { otp, expires  } = TOTP.generate(target.secret)
          target.code = otp
          target.expires = expires
          target.time = getSeconds(expires)
          serverData.value.push(target)
          handleRefreshOpt(target.id)
        } catch (err) {
          console.log('init err', err)
        }
      }
    }
  })
})

onBeforeUnmount(() => {
  timeMap.forEach((key, value) => {
    console.log('onBeforeUnmount clearInterval key:', key)
    clearInterval(value)
  })
})

const handleScan = () => {
  chrome.tabs.captureVisibleTab(undefined, { format: 'jpeg' }, (dataUrl) => {
    const codeReader = new BrowserMultiFormatReader()
    codeReader.decodeFromImage(undefined, dataUrl).then(result => {
      console.log(`result:${result.text}`)
      const pareData = parseOtpAuthUrl(result.text)
      console.log('pareData:', pareData)

      const { otp, expires  } = TOTP.generate(pareData.secret)
      const data = {
        id: uuidv4(),
        name: pareData.issuer + " " + pareData.accountName,
        secret: pareData.secret,
        code: otp,
        expires: expires,
        time: getSeconds(expires)
      }

      chrome.storage.local.get(["authKey"]).then((result) => {
        console.log("Value currently is ", result.authKey)
        let list = []
        if (result.authKey) {
          list = JSON.parse(result.authKey)
        }
        console.log('getStoreData:', list)
        list.push(data)

        chrome.storage.local.set(
          { 
            'authKey': JSON.stringify(list) 
          }
        ).then(() => {
          serverData.value.push(data)
          handleRefreshOpt(data.id)
          ElMessage({
            duration: 300,
            message: '添加成功',
            grouping: true,
            type: 'success',
          })
        }).catch(err => {
          console.log(`chrome storage err`, err)
          ElMessage({
            duration: 300,
            message: '添加失败',
            grouping: true,
            type: 'error',
          })
        })
      })
    }).catch(err => {
      console.log(err)
      ElMessage({
        duration: 300,
        message: '扫码失败',
        grouping: true,
        type: 'error',
      })
    })
  })
}

const handleAdd = () => {
  from.value = {
    name: '',
    secret: ''
  }
  showFlag.value = true
}

const handleConfirm = () => {
  if (!from.value || !from.value.name || !from.value.secret) {
    ElMessage.error('参数不能为空')
    return
  }

  try{
    const { otp, expires  } = TOTP.generate(from.value.secret)
    const data = {
      id: uuidv4(),
      name: from.value.name,
      secret: from.value.secret,
      code: otp,
      expires: expires,
      time: getSeconds(expires)
    }

    chrome.storage.local.get(["authKey"]).then((result) => {
      let list = []
      if (result.authKey) {
        list = JSON.parse(result.authKey)
      }
      console.log('getStoreData:', list)
      list.push(data)

      chrome.storage.local.set(
        { 
          'authKey': JSON.stringify(list) 
        }
      ).then(() => {
        serverData.value.push(data)
        showFlag.value = false
        handleRefreshOpt(data.id)
        ElMessage({
          duration: 300,
          message: '添加成功',
          grouping: true,
          type: 'success',
        })
      }).catch(err => {
        console.log(`chrome storage err`, err)
        ElMessage({
          duration: 300,
          message: '添加失败',
          grouping: true,
          type: 'error',
        })
      })
    })
  } catch (err) {
    console.log(`handleConfirm err`, err)
    ElMessage({
      duration: 300,
      message: '添加失败',
      grouping: true,
      type: 'error',
    })
  }
}

const handleRefreshOpt = (id) => {
  const time = setInterval(() => {
    const data = serverData.value.find(i => i.id === id)
    const second = getSeconds(data.expires)
    if (second > 0) {
      data.time = second
    } else {
      const { otp, expires  } = TOTP.generate(data.secret)
      data.code = otp
      data.expires = expires
      data.time = getSeconds(expires)
    }
  }, 1000)
  timeMap.set(id, time)
}

const getSeconds = timestamp => {
  // 计算时间差（毫秒）
  const ms = Math.abs(timestamp - Date.now())
  // 将时间差转换为秒
  return parseInt(ms / 1000)
}

const handleDelete = (id) => {
  const data = serverData.value.find(i => i.id === id)
  const filterData = serverData.value.filter(i => i.id !== id)
  serverData.value = filterData
  chrome.storage.local.set(
    { 
      'authKey': JSON.stringify(filterData) 
    }
  ).catch(err => {
    console.log(`chrome storage err`, err)
    ElMessage.error('删除失败')
  })
  const time = timeMap.get(id)
  if (time) {
    clearInterval(time)
  }
  chrome.storage.local.get(["authKeyHis"]).then((result) => {
    let list = []
    if (result.authKeyHis) {
      list = JSON.parse(result.authKeyHis)
    }
    list.push(data)
    chrome.storage.local.set(
      { 
        'authKeyHis': JSON.stringify(list) 
      }
    )
  })
}

const parseOtpAuthUrl = (url) => {
  const parsedUrl = new URL(url)

  // 解析路径部分
  const pathParts = parsedUrl.pathname.split(':')
  const issuer = pathParts[0].replace('/totp/', '')
  const accountName = pathParts[1]

  // 解析查询参数部分
  const searchParams = new URLSearchParams(parsedUrl.search.slice(1))
  const secret = searchParams.get('secret')
  const issuerFromParams = searchParams.get('issuer')

  // 如果查询参数中有 issuer，优先使用查询参数中的 issuer
  const finalIssuer = issuerFromParams || issuer

  return {
    issuer: finalIssuer,
    accountName: accountName,
    secret: secret
  }
}

const handleCopy = (data) => {
  navigator.clipboard.writeText(data.code).then(() => {
    ElMessage({
      duration: 300,
      message: '复制成功',
      grouping: true,
      type: 'success',
    })
  })
}

const handleOpenHis = () => {
  hisFlag.value = true
  chrome.storage.local.get(["authKeyHis"]).then((result) => {
    let list = []
    if (result.authKeyHis) {
      list = JSON.parse(result.authKeyHis)
    }
    hisList.value = list
  })
}

const handleHisDelete = (id) => {
  chrome.storage.local.get(["authKeyHis"]).then((result) => {
    if (!result.authKeyHis) {
      return
    }
    const list = JSON.parse(result.authKeyHis)
    const filterList = list.filter(i => i.id !== id)
    chrome.storage.local.set(
      { 
        'authKeyHis': JSON.stringify(filterList) 
      }
    ).then(() => {
      hisList.value = filterList
    })
  })
}

const handleHisBack = (data) => {
  const { otp, expires  } = TOTP.generate(data.secret)
  data.otp = otp
  data.expires = expires

  chrome.storage.local.get(["authKey"]).then((result) => {
    let list = []
    if (result.authKey) {
      list = JSON.parse(result.authKey)
    }
    list.push(data)

    chrome.storage.local.set(
      { 
        'authKey': JSON.stringify(list) 
      }
    ).then(() => {
      serverData.value.push(data)
      handleRefreshOpt(data.id)
      handleHisDelete(data.id)
      ElMessage({
        duration: 300,
        message: '恢复成功',
        grouping: true,
        type: 'success',
      })
    }).catch(err => {
      console.log(`chrome storage err`, err)
      ElMessage({
        duration: 300,
        message: '恢复失败',
        grouping: true,
        type: 'error',
      })
    })
  })
}

</script>

<style lang="less">
.main-wrap {
  width: 300px;

  .tool-warp {
    display: flex;
    justify-content: flex-end;
    justify-items: center;
    padding-bottom: 5px;
    padding-right: 15px;
  }

  .code-wrap {
    padding-bottom: 5px;
    padding-right: 10px;

    .code-item {
      margin-top: 10px;
      border-radius: 8px;
      background-color: #F0F2F5;
      cursor: pointer;

      .code-title {
        display: flex;
        flex-wrap: nowrap;
        padding: 5px;
        height: 10px;

        .title-text {
          width: 280px;
        }

        .title-time {
          width: 20px;
          font-size: 17px;
          color: #E6A23C;
        }

      }

      .tool-wrap {
        display: flex;
        flex-wrap: nowrap;
        padding-bottom: 10px;

        .left-tool {
          display: flex;
          width: 200px;
          justify-items: center;
          color: #409EFF;
          padding-top: 5px;
          padding-left: 10px;

          h1 {
            margin: 0;
            letter-spacing: 4px;
          }
        }

        .right-tool {
          display: flex;
          justify-items: center;
          justify-content: flex-end;
          width: 100px;
          padding-top: 10px;
          padding-left: 10px;
          padding-right: 10px;
        }
      }
    }
  }
}

</style>
